/**
 * 
 */
package cu.ds.logicalsync.fytasrealm.communication;

import java.io.IOException;
import java.util.Date;

import cu.ds.logicalsync.fytasrealm.communication.constants.MapStatusRequest;

import net.jxta.endpoint.Message;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.pipe.OutputPipe;
import net.jxta.pipe.OutputPipeEvent;
import net.jxta.pipe.OutputPipeListener;
import net.jxta.pipe.PipeService;
import net.jxta.protocol.PipeAdvertisement;

/**
 * Utilize PipeService for broadcast/direct sending message to listening peer
 * 
 * @author r.vashira
 */
public class MessageSender implements OutputPipeListener {
	
	/** Member Variables **/
	private JxtaConnection connection;
	private Message message;
	private OutputPipe outputPipe;
	

	/**
	 * Default Constructor
	 * @param connection
	 */
	public MessageSender(JxtaConnection connection) {
		super();
		this.connection = connection;
	}

	/** Public Methods **/
	
	public void sendBroadCast(String message) {
		PipeService pipeService = connection.getPipeService();
		
		// hold message until pipe resolution finish
		this.message = createSimpleMessage(message); // TODO: create Message based on given args
		
		PipeAdvertisement mapPipeAdv = connection.getMapPipeAdvertisement();
		
		// issue a pipe resolution asynchronously. outputPipeEvent() is called
        // once the pipe has resolved
        try {
			pipeService.createOutputPipe(mapPipeAdv, this);
		} catch (IOException e) {
			System.out.println("OutputPipe creation failure");
			e.printStackTrace();
			System.exit(-1);
		}
	}
	
	public void sendComplexBroadCast() {
		PipeService pipeService = connection.getPipeService();
		this.message = createAdvanceMessage();
		
		PipeAdvertisement mapPipeAdv = connection.getMapPipeAdvertisement();
		
		// issue a pipe resolution asynchronously. outputPipeEvent() is called
        // once the pipe has resolved
        try {
			pipeService.createOutputPipe(mapPipeAdv, this);
		} catch (IOException e) {
			System.out.println("OutputPipe creation failure");
			e.printStackTrace();
			System.exit(-1);
		}
	}

	/* (non-Javadoc)
	 * @see net.jxta.pipe.OutputPipeListener#outputPipeEvent(net.jxta.pipe.OutputPipeEvent)
	 */
	public void outputPipeEvent(OutputPipeEvent event) {
		System.out.println("Received the output pipe resolution event");
		// get the output pipe object
		outputPipe = event.getOutputPipe();

		try {
			System.out.println("Sending message");
			// send the message
			outputPipe.send(this.message);
			System.out.println("message sent");
		} catch (IOException e) {
			System.out.println("failed to send message");
			e.printStackTrace();
			System.exit(-1);
		}
		// TODO: Notify listeners
	}
	
	/** Helper Methods **/
	private Message createSimpleMessage(String message) {
		Message msg = new Message();
		
		//StringMessageElement sme = new StringMessageElement("RegisterWorldInMap", "0,0", null);
		StringMessageElement sme = new StringMessageElement("SimpleBroadcast", message, null);
		
		msg.addMessageElement(sme);
		
		return msg;
	}
	
	private Message createAdvanceMessage() {
		Message msg = JxtaUtil.createRequestMessage(MapStatusRequest.RegisterWorldInMap, "NameSpace0");
		
		JxtaUtil.addStringToMessage(msg, "NameSpace1", "Element1", "ValueA");
		JxtaUtil.addStringToMessage(msg, "NameSpace1", "Element2", "ValueB");
		JxtaUtil.addStringToMessage(msg, "NameSpace2", "Element1", "ValueC");
		JxtaUtil.addStringToMessage(msg, "NameSpace2", "Element2", "ValueD");
		JxtaUtil.addStringToMessage(msg, "NameSpace2", "Element2", "ValueE");
		
		return msg;
	}
}
